import { fromEvent, interval, animationFrameScheduler, merge } from 'rxjs'
import {
  map,
  scan,
  distinctUntilChanged,
  startWith,
  filter
} from 'rxjs/operators'
import { FPS, KEYCODE, LOW_SPEED, HIGH_SPEED } from './constant'

/** 1.浏览器刷新心跳 */
export const ticker$ = interval(1000 / FPS, animationFrameScheduler).pipe(
  // 获取当前时间和
  map<number, Time>(() => ({
    time: new Date().getTime(),
    delay: 0
  })),
  scan<Time, Time>((total, current) => ({
    time: current.time,
    delay: current.time - total.time
  }))
)

/** 2.键盘按下：回车键开始 + 方向键改变方向 + 空格键加速 */
export const keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown')

/** 3.键盘松开：松开空格键减速 */
export const keyUp$ = fromEvent<KeyboardEvent>(document, 'keyup')

/** 4.方向键：方向控制 */
export const direction$ = keyDown$.pipe(
  map<KeyboardEvent, number>((e) => e.keyCode),
  // 过滤非方向键
  filter<number>((keyCode) =>
    [KEYCODE.UP, KEYCODE.DOWN, KEYCODE.LEFT, KEYCODE.RIGHT].includes(keyCode)
  ),
  // 初始方向向左
  startWith<number, number>(KEYCODE.LEFT),
  // 本次方向键和上次方向键 相同/相反 则方向不变
  scan<number, number>((total, current) => {
    if (total === current || Math.abs(current - total) === 2) {
      return total
    }
    return current
  }),
  // 前后两次值相同则过滤
  distinctUntilChanged()
)

/** 5.空格键：速度控制 */
export const speed$ = merge(keyDown$, keyUp$).pipe(
  // 过滤非空格键
  filter<KeyboardEvent>((e) => [KEYCODE.SPACE].includes(e.keyCode)),
  // 按下加速 / 松开减速
  map<KeyboardEvent, number>((e) =>
    e.type === 'keydown' ? HIGH_SPEED : LOW_SPEED
  ),
  // 初始速度低速
  startWith<number, number>(LOW_SPEED)
)
